package com.jrfid.smartcabinet.demo.ui.inventory

import android.app.Application
import android.view.View
import android.widget.AdapterView
import androidx.databinding.ObservableArrayList
import androidx.databinding.ObservableField
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.viewModelScope
import androidx.navigation.NavController
import com.blankj.utilcode.util.ToastUtils
import com.jrfid.devicemanager.library.CMDData
import com.jrfid.devicemanager.library.DeviceType
import com.jrfid.devicemanager.library.DevicesManager
import com.jrfid.devicemanager.library.packet.UHFPacketData
import com.jrfid.devicemanager.library.packet.UHFTagInfoModel
import com.jrfid.smartcabinet.demo.R
import com.jrfid.smartcabinet.demo.base.BaseViewModel
import com.jrfid.smartcabinet.demo.model.CabinetConfigInfoModel
import com.jrfid.smartcabinet.demo.model.TagInfoModel
import com.jrfid.smartcabinet.demo.ui.inventory.adapter.TagInfoAdapter
import com.jrfid.smartcabinet.demo.utils.Config
import com.jrfid.smartcabinet.demo.utils.KTDataUtils
import com.xuhao.didi.socket.client.sdk.client.connection.IConnectionManager
import kotlinx.coroutines.*
import java.util.*
import kotlin.experimental.and
import kotlin.math.max
import kotlin.math.min

class InventoryViewModel(application: Application, navController: NavController) : BaseViewModel(application, navController) {

    val cabinetList = ObservableArrayList<String>()
    val tagAdapter = TagInfoAdapter()
    private val cabinetInfoList = Config.getCabinetList()
    val inventoryBtnText = ObservableField(getString(R.string.btn_start_inventory))
    val inventoryTotal = ObservableField("")
    val inventoryTime = ObservableField("")
    val inventoryMinRssi = ObservableField("")
    val inventoryMaxRssi = ObservableField("")
    private var selectInventoryObjectPosition = -1
    private var isInventorying = false
    private val managerList = mutableListOf<IConnectionManager>()
    private var inventoryTimer: Timer? = null
    private var startTime = 0L
    private val cabinetNameMap = hashMapOf<Int, String>()
    private var minRssi = 0
    private var maxRssi = 0
//    private var ledTimer: Timer = timer(null, false, 1000, 500) {
//        val size = tagAdapter.getLedEpcList().size
//        if (size > 0) {
//            if (currentIndex >= size) {
//                currentIndex = 0
//            }
//            val item = tagAdapter.getLedEpcList()[currentIndex]
//            item.cabinetIp?.let { ip ->
//                item.cabinetPort?.let { port ->
//                    val manager = TCPConnectUtils.getConnectionManager(ip, port)
//                    if (manager.isConnect) {
//                        manager.send(SocketMsgModel(CMDData.R2000.selectLabel(item.epc)))
//                        Thread.sleep(50)
//                        manager.send(SocketMsgModel(CMDData.R2000.readLabelData(1, 4, 1, "00000000")))
//                    }
//                }
//            }
//            currentIndex++
//        }
//    }
//    private var currentIndex = 0


//    private val socketListener = object : SocketActionAdapter() {
//        override fun onSocketConnectionSuccess(info: ConnectionInfo?, action: String?) {
//            super.onSocketConnectionSuccess(info, action)
//        }
//
//        override fun onSocketConnectionFailed(info: ConnectionInfo, action: String?, e: Exception?) {
//            super.onSocketConnectionFailed(info, action, e)
//            ToastUtils.showShort("${cabinetNameMap[info.ip]}" + getString(R.string.text_connect_error))
//        }
//
//        override fun onSocketDisconnection(info: ConnectionInfo, action: String?, e: Exception?) {
//            super.onSocketDisconnection(info, action, e)
//            ToastUtils.showShort("${cabinetNameMap[info.ip]}" + getString(R.string.text_connect_error_disconnect))
//        }
//
//        override fun onSocketReadResponse(info: ConnectionInfo, action: String, data: OriginalData) {
//            super.onSocketReadResponse(info, action, data)
//            val body = data.bodyBytes
//            val header = data.headBytes
//            LogUtils.dTag(TAG, "${info.ip}收到数据：${KTDataUtils.byteArrayToHex(data.headBytes)} ${KTDataUtils.byteArrayToHex(data.bodyBytes)}")
//            if (header.size == 2 && header[1] >= 0x04) {
//                when (body[1]) {
//                    0x8B.toByte() -> {
//                        //读到标签
//                        val len = header[1].toInt()
//                        if (len > 10) {
//                            val epc = KTDataUtils.byteArrayToHexTrim(body.toList().subList(5, len - 2).toByteArray())
//                            val rssi = body[len - 2].toInt() - 128
//                            val tagInfoModel = TagInfoModel().apply {
//                                this.cabinetName = cabinetNameMap[info.ip] ?: ""
//                                this.cabinetIp = info.ip
//                                this.cabinetPort = info.port
//                                this.epc = epc
//                                this.rssiMin = rssi
//                                this.rssiMax = rssi
//                                this.count = 1
//                            }
//                            if (minRssi == 0 && maxRssi == 0) {
//                                minRssi = rssi
//                                maxRssi = rssi
//                            } else {
//                                minRssi = min(minRssi, rssi)
//                                maxRssi = max(maxRssi, rssi)
//                            }
//                            ThreadUtils.runOnUiThread {
//                                tagAdapter.addData(tagInfoModel)
//                                inventoryTotal.set(tagAdapter.data.size.toString())
//                                inventoryMinRssi.set(minRssi.toString())
//                                inventoryMaxRssi.set(maxRssi.toString())
//                            }
//                        }
//                    }
//                    0x85.toByte() -> {
//                        //设置了选中标签
//
//                    }
//                }
//            }
//        }
//
//        override fun onSocketWriteResponse(info: ConnectionInfo, action: String?, data: ISendable) {
//            super.onSocketWriteResponse(info, action, data)
//            LogUtils.dTag(TAG, "${info.ip}发送数据：${KTDataUtils.byteArrayToHex(data.parse())}")
//        }
//    }

//    private val onReceiveMainBoardDataListener = object : Manager.OnSerialPortDataListener {
//
//        override fun onDataReceived(byteArray: ByteArray) {
////            LogUtils.d("main recv: ${KTDataUtils.byteArrayToHexTrim(byteArray)}")
//            val len = byteArray[1].toInt()
//            val dataLen = len - 3
//            val cmd = byteArray[3]
//            val address = byteArray[2]
//            when (cmd) {
//                CMDData.Cabinet.CMD_UHF_DATA -> {
//                    val uhfData = ByteArray(dataLen)
//                    System.arraycopy(byteArray, 4, uhfData, 0, uhfData.size)
//                    onReceivedUHFData(address, uhfData)
//                }
//            }
//        }
//
//        override fun onDataSend(byteArray: ByteArray) {
////            LogUtils.d("main send: ${KTDataUtils.byteArrayToHexTrim(byteArray)}")
//        }
//
//    }

    private val listener = object : DevicesManager.OnDeviceDataCallback {

        override fun onDataReceived(deviceType: DeviceType, address: Byte, byteArray: ByteArray) {
            if (deviceType == DeviceType.UHF) {
                val model = UHFPacketData(byteArray)
                when (model.cmd) {
                    (0x89).toByte(), (0x8A).toByte(), (0x8B).toByte() -> {
                        //盘存标签
                        if (model.len < 10) {
                            //盘存错误
                            //盘存错误
//                            if (address == 0x01.toByte()) {
//                                sendInventoryCMD1()
//                            } else if (address == 0x02.toByte()) {
//                                sendInventoryCMD2()
//                            }
                        } else if (model.len == 10) {
                            //盘存结束
//                            if (address == 0x01.toByte()) {
//                                sendInventoryCMD1()
//                            } else if (address == 0x02.toByte()) {
//                                sendInventoryCMD2()
//                            }
                        } else {
                            //盘存到标签
                            val tag = UHFTagInfoModel(model.data)
                            val tagInfoModel = TagInfoModel().apply {
                                this.cabinetName = cabinetNameMap[address.toInt()] ?: ""
                                this.epc = tag.epc
                                this.rssiMin = tag.rssi
                                this.rssiMax = tag.rssi
                                this.count = 1
                                this.cabinetAddress = address.toInt()
                            }
                            if (minRssi == 0 && maxRssi == 0) {
                                minRssi = tag.rssi
                                maxRssi = tag.rssi
                            } else {
                                minRssi = min(minRssi, tag.rssi)
                                maxRssi = max(maxRssi, tag.rssi)
                            }
                            inventoryMinRssi.set(minRssi.toString())
                            inventoryMaxRssi.set(maxRssi.toString())
                            viewModelScope.launch(Dispatchers.Main) {
                                tagAdapter.addData(tagInfoModel)
                                inventoryTotal.set(tagAdapter.data.size.toString())
                            }
                        }
                    }
                }
            }
        }

        override fun onDataSend(deviceType: DeviceType, address: Byte, byteArray: ByteArray) {

        }
    }

//    private fun onReceivedUHFData(address: Byte, byteArray: ByteArray) {
//        val len = byteArray[1].toInt()
//        val cmd = byteArray[3]
//        when (cmd) {
//            (0x89).toByte(), (0x8A).toByte(), (0x8B).toByte() -> {
//                //盘存标签
//                if (len < 10) {
//                    //盘存错误
//                    if (address == 0x01.toByte()) {
//                        sendInventoryCMD1()
//                    } else if (address == 0x02.toByte()) {
//                        sendInventoryCMD2()
//                    }
//                } else if (len == 10) {
//                    //盘存结束
//                    if (address == 0x01.toByte()) {
//                        sendInventoryCMD1()
//                    } else if (address == 0x02.toByte()) {
//                        sendInventoryCMD2()
//                    }
//                } else {
//                    //盘存到标签
//                    viewModelScope.launch {
//                        val time = System.currentTimeMillis()
//                        val epcLen = len - 7
//                        val epcData = ByteArray(epcLen)
//                        System.arraycopy(byteArray, 7, epcData, 0, epcLen)
//                        val epc = KTDataUtils.byteArrayToHexTrim(epcData)
//                        val rssi = (byteArray[len] and 127) - 129
//                        if (rssi > -100) {
//                            val tagInfoModel = TagInfoModel().apply {
//                                this.cabinetName = cabinetNameMap[address.toInt()] ?: ""
//                                this.epc = epc
//                                this.rssiMin = rssi
//                                this.rssiMax = rssi
//                                this.count = 1
//                                this.cabinetAddress = address.toInt()
//                            }
//                            if (minRssi == 0 && maxRssi == 0) {
//                                minRssi = rssi
//                                maxRssi = rssi
//                            } else {
//                                minRssi = min(minRssi, rssi)
//                                maxRssi = max(maxRssi, rssi)
//                            }
//                            withContext(Dispatchers.Main) {
//                                tagAdapter.addData(tagInfoModel)
//                                inventoryTotal.set(tagAdapter.data.size.toString())
//                                inventoryMinRssi.set(minRssi.toString())
//                                inventoryMaxRssi.set(maxRssi.toString())
//                            }
//                        }
//                    }
//                }
//            }
//        }
//    }

    private var retryInventoryJob1: Job? = null

    private fun sendInventoryCMD1() {
        retryInventoryJob1?.cancel()
        if (isInventorying) {
            DevicesManager.instance.sendData(
                DeviceType.UHF, 0x01,
                CMDData.R2000.fastSwitchAntInventoryFor8Ant(
                    session = 1,
                    ant4 = false,
                    ant5 = false,
                    ant6 = false,
                    ant7 = false
                )
            )
            retryInventoryJob1 = viewModelScope.launch {
                delay(300)
                sendInventoryCMD1()
            }
        }
    }

    private var retryInventoryJob2: Job? = null

    private fun sendInventoryCMD2() {
        retryInventoryJob2?.cancel()
        if (isInventorying) {
            DevicesManager.instance.sendData(
                DeviceType.UHF, 0x02,
                CMDData.R2000.fastSwitchAntInventoryFor8Ant(
                    session = 1,
                    ant7 = false
                )
            )
            retryInventoryJob2 = viewModelScope.launch {
                delay(300)
                sendInventoryCMD2()
            }
        }
    }

    private fun sendLoopInventory1() {
        if (isInventorying) {
            DevicesManager.instance.startInventory(
                10,
                address = 0x01,
                CMDData.R2000.fastSwitchAntInventoryFor8Ant(ant4 = false, ant5 = false, ant6 = false, ant7 = false, session = 1)
            )
        }
    }

    private fun sendLoopInventory2() {
        if (isInventorying) {
            DevicesManager.instance.startInventory(
                10,
                address = 0x02,
                CMDData.R2000.fastSwitchAntInventoryFor8Ant(ant7 = false, session = 1)
            )
        }
    }

    private var ledJob: Job? = null
    private fun lightLedTag() {
        ledJob?.cancel()
        ledJob = viewModelScope.launch {
            while (true) {
                tagAdapter.getLedTag()?.let { item ->
                    DevicesManager.instance.sendData(deviceType = DeviceType.UHF, address = item.cabinetAddress.toByte(), byteArray = CMDData.R2000.selectLabel(item.epc))
                    delay(10)
                    DevicesManager.instance.sendData(deviceType = DeviceType.UHF, address = item.cabinetAddress.toByte(), byteArray = CMDData.R2000.setDeviceWorkAntenna(0x02))
                    delay(10)
                    DevicesManager.instance.sendData(deviceType = DeviceType.UHF, address = item.cabinetAddress.toByte(), byteArray = CMDData.R2000.readLabelData(1, 4, 1))
                }
                delay(100)
            }
        }
    }

    init {
//        if (cabinetInfoList.isNotEmpty()) {
//            selectInventoryObjectPosition = 0
//            cabinetList.add(getString(R.string.text_inventory_cabinet_all))
//            cabinetInfoList.forEach {
//                cabinetList.add(it.name.get())
//                cabinetNameMap[it.address.get()!!.toInt()] = it.name.get()!!
//            }
//        }
        tagAdapter.setOnItemClickListener { adapter, view, position ->
            if (!isInventorying) {
                val item = tagAdapter.getItem(position)
                tagAdapter.selectLedEpc(item, position)
            }
        }
    }

    override fun onCreate(owner: LifecycleOwner) {
        super.onCreate(owner)
        if (cabinetInfoList.isNotEmpty()) {
            selectInventoryObjectPosition = 0
            cabinetList.add(getString(R.string.text_inventory_cabinet_all))
            cabinetInfoList.forEach {
                cabinetList.add(it.name.get())
                cabinetNameMap[it.address.get()!!.toInt()] = it.name.get()!!
            }
        }
        DevicesManager.instance.addOnDeviceDataListener(listener)
//        MainBoardManager.instance.addOnSerialPortDataListener(onReceiveMainBoardDataListener)
    }

    fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
        selectInventoryObjectPosition = position
    }

    fun onClickBackBtn(view: View) {
        navController.navigateUp()
    }

    fun onClickInventoryBtn(view: View) {
        if (isInventorying) {
            //停止盘存
            stopInventory()
        } else {
            //开始盘存
            if (cabinetInfoList.isEmpty()) {
                ToastUtils.showShort(getString(R.string.text_config_cabinet_info))
                return
            }
            inventoryTotal.set("0")
            inventoryTime.set("0")
            minRssi = 0
            maxRssi = 0
            inventoryMaxRssi.set("")
            inventoryMinRssi.set("")
            inventoryBtnText.set(getString(R.string.btn_stop_inventory))
            isInventorying = true
//            clearManager()
            tagAdapter.setList(null)
//            connectReaderAndInventory()
            startInventory()
        }
    }

    private fun stopInventory() {
        lightLedTag()
        inventoryBtnText.set(getString(R.string.btn_start_inventory))
        isInventorying = false
        retryInventoryJob1?.cancel()
        retryInventoryJob2?.cancel()
        inventoryTimerJob?.cancel()
    }

    private var inventoryTimerJob: Job? = null
    private fun startInventory() {
        ledJob?.cancel()
        inventoryTimerJob?.cancel()
        startTime = System.currentTimeMillis()
        inventoryTimerJob = viewModelScope.launch {
            while (true) {
                val time = System.currentTimeMillis() - startTime
                withContext(Dispatchers.Main) {
                    inventoryTime.set("${(time / 1000).toInt()}.${time % 1000}")
                }
                if (time >= 10 * 1000) {
                    stopInventory()
                    break
                }
                delay(100)
            }
        }
        if (selectInventoryObjectPosition == 0) {
            //选择全部
            if (cabinetInfoList.size == 1) {
                //只配置了主柜
//                sendInventoryCMD1()
                sendLoopInventory1()
            } else {
//                sendInventoryCMD1()
//                sendInventoryCMD2()
                sendLoopInventory1()
                sendLoopInventory2()
            }
        } else if (selectInventoryObjectPosition == 1) {
//            sendInventoryCMD1()
            sendLoopInventory1()
        } else if (selectInventoryObjectPosition == 2) {
//            sendInventoryCMD2()
            sendLoopInventory2()
        }
    }

    private fun clearManager() {
//        managerList.forEach {
//            it.unRegisterReceiver(socketListener)
//        }
//        managerList.clear()
    }

    private fun connectReaderAndInventory() {
//        if (selectInventoryObjectPosition == 0) {
//            //选择全部
//            if (cabinetInfoList.size == 1) {
//                //只配置了主柜
//                connectReader(cabinetInfoList[0])
//            } else {
//                cabinetInfoList.forEach {
//                    connectReader(it)
//                }
//            }
//        } else {
//            connectReader(cabinetInfoList[selectInventoryObjectPosition - 1])
//        }
//        startTime = System.currentTimeMillis()
//        inventoryTimer = timer(null, false, 100L, 50L) {
//            val time = System.currentTimeMillis() - startTime
//            inventoryTime.set("${(time / 1000).toInt()}.${time % 1000}")
//            managerList.forEach {
////                it.send(SocketMsgModel(CMDData.R2000.realTimeInventory()))
//                it.send(SocketMsgModel(CMDData.R2000.realTimeInventoryCustomizedSession(1)))
//            }
//        }
    }

    private fun connectReader(model: CabinetConfigInfoModel) {
//        val manager = TCPConnectUtils.getConnectionManager(model.readerIP.get()!!, model.readerPort.get()!!.toIntOrNull() ?: 4001)
//        if (!manager.isConnect) {
//            TCPConnectUtils.connectRFIDDevice(model.readerIP.get(), model.readerPort.get()?.toIntOrNull(), socketListener)
//        } else {
//            manager.registerReceiver(socketListener)
//        }
//        managerList.add(manager)
    }

    override fun onPause(owner: LifecycleOwner) {
        super.onPause(owner)
        stopInventory()
    }

    override fun onDestroy(owner: LifecycleOwner) {
        isInventorying = false
        retryInventoryJob1?.cancel()
        retryInventoryJob2?.cancel()
        DevicesManager.instance.removeOnDeviceDataListener(listener)
//        MainBoardManager.instance.removeOnSerialPortDataListener(onReceiveMainBoardDataListener)
//        inventoryTimer?.cancel()
//        ledTimer.cancel()
//        clearManager()
        super.onDestroy(owner)
    }
}